#pragma once

#include "DXAMLCommon.h"

#include "XamlReader.h"
#include "XamlNode.h"
#include "XamlWriter.h"


class XamlOptimizedNodeList :
	xenable_shared_from_this<XamlOptimizedNodeList>
{
public:

	enum NodeListFlags
	{
		nlfNone = 0x0,
		nlfIsUnknown = 0x1,
		nlfIsRetrieved = 0x2,
		nlfHasLineDelta = 0x4,
		nlfIsLineDeltaNegative = 0x8,
		nlfHasPositionDelta = 0x10,
		nlfIsPositionDeltaNegative = 0x20,
	};


	class XamlOptimizedNodeListReader :
		public XamlReader
	{

	public: 
		XamlOptimizedNodeListReader(const xshared_ptr<XamlSchemaContext> & spXamlSchemaContext, const xshared_ptr<XamlOptimizedNodeList> & spXamlOptimizedNodeList, XUINT32 nodeCount);
		virtual HRESULT Read();
		virtual const XamlNode & CurrentNode();
		virtual HRESULT GetSchemaContext(xshared_ptr<XamlSchemaContext> & outSchemaContext);
	private: 
		HRESULT ReadCommonInfo(enum XamlNode::XamlNodeType & nodeType);
		HRESULT ReadLineInfo();
		xweak_ptr<XamlSchemaContext> m_spXamlSchemaContext;
		xshared_ptr<XamlOptimizedNodeList> m_spXamlOptimizedNodeList;
		XUINT32 m_nextIndex;
		XUINT32 m_lastIndex;
		XamlNode m_currentNode;
		enum NodeListFlags m_nodeFlags;
		XamlLineInfo m_previousLineInfo;



	};


	class XamlOptimizedNodeListWriter :
		public XamlWriter
	{
	public: 
		XamlOptimizedNodeListWriter();
		XamlOptimizedNodeListWriter(const xshared_ptr<XamlSchemaContext> & spXamlSchemaContext, const xshared_ptr<XamlOptimizedNodeList> & spXamlOptimizedNodeList);
		virtual HRESULT WriteObject(const xshared_ptr<XamlType> & inType, XBOOL bIsObjectFromMember);
		virtual HRESULT WriteEndObject();
		virtual HRESULT WriteMember(const xshared_ptr<XamlProperty> & inProperty);
		virtual HRESULT WriteEndMember();
		virtual HRESULT WriteValue(const xshared_ptr<XamlQualifiedObject> & value);
		virtual HRESULT WriteNamespace(const xshared_ptr<CXString> & spPrefix, const xshared_ptr<XamlNamespace> & spXamlNamespace);
		virtual HRESULT Close();
		virtual HRESULT GetSchemaContext(xshared_ptr<XamlSchemaContext> & outSchemaContext);
	private: 
		HRESULT WriteCommonInfo(enum XamlNode::XamlNodeType nodeType, enum XamlOptimizedNodeList::NodeListFlags nodeFlags);
		xshared_ptr<XamlOptimizedNodeList> m_spXamlOptimizedNodeList;
		xshared_ptr<XamlSchemaContext> m_spXamlSchemaContext;
		XamlLineInfo m_previousLineInfo;
	};


private: 
	XamlOptimizedNodeList();
public: 
	XamlOptimizedNodeList(const xshared_ptr<XamlSchemaContext> & spXamlSchemaContext);
	HRESULT get_Writer(xshared_ptr<XamlWriter> & outWriter);
	HRESULT get_Reader(xshared_ptr<XamlReader> & outReader);
	XUINT32 get_Count();
	HRESULT Clear();
	HRESULT Reserve(unsigned int);
	HRESULT ReserveBasedOn(const xshared_ptr<XamlOptimizedNodeList> & spOther);
	HRESULT Close();
protected: 
	HRESULT AddNodeType(enum XamlNode::XamlNodeType nodeType);
	HRESULT AddFlags(enum XamlOptimizedNodeList::NodeListFlags flags);
	HRESULT AddProperty(const xshared_ptr<XamlProperty> & spXamlProperty);
	HRESULT AddType(const xshared_ptr<XamlType> & spXamlType);
	HRESULT AddXamlNamespace(const xshared_ptr<XamlNamespace> & spXamlNamespace, XBOOL fIsUnknown);
	HRESULT AddValue(const xshared_ptr<XamlQualifiedObject> & spXqo);
	HRESULT AddString(const xshared_ptr<CXString> & spString);
	HRESULT AddUnsignedInt(XUINT32);
	HRESULT WriteByte(XUINT8 bValue);
	HRESULT Write7BitEncodedInt(XUINT32 uiValue);
	HRESULT ReadNodeTypeAt(enum XamlNode::XamlNodeType & nodeType, XUINT32 & ruiStartingIndex);
	HRESULT ReadFlagsAt(enum XamlOptimizedNodeList::NodeListFlags & flags, XUINT32 & ruiStartingIndex);
	HRESULT ReadPropertyAt(xshared_ptr<XamlProperty> & spXamlProperty, XUINT32 & ruiStartingIndex);
	HRESULT ReadTypeAt(xshared_ptr<XamlType> & spXamlType, XUINT32 & ruiStartingIndex);
	HRESULT ReadXamlNamespaceAt(xshared_ptr<XamlNamespace> & spXamlNamespace, XBOOL fIsUnknown, XUINT32 & ruiStartingIndex);
	HRESULT ReadValueAt(xshared_ptr<XamlQualifiedObject> & spValue, XUINT32 & ruiStartingIndex);
	HRESULT ReadStringAt(xshared_ptr<CXString> & spString, XUINT32 & ruiStartingIndex);
	HRESULT ReadUnsignedIntAt(XUINT32 & ruValue, XUINT32 & ruiStartingIndex);
	HRESULT ReadByteAt(XUINT8 & bValue, XUINT32 & ruiStartingIndex);
	HRESULT Read7BitEncodedInt(XUINT32 & ruiValue, XUINT32 & ruiStartingIndex);
private: 
	HRESULT GetSchemaContext(xshared_ptr<XamlSchemaContext> & outSchemaContext);
	xvector<XUINT8> m_bytes;
	xvector<xshared_ptr<XamlQualifiedObject> > m_values;
	xvector<xshared_ptr<CXString> > m_strings;
	xvector<xshared_ptr<XamlNamespace> > m_unknownNamespaces;
	XBOOL m_fReadMode;
	xshared_ptr<XamlSchemaContext> m_spXamlSchemaContext;
	xweak_ptr<XamlOptimizedNodeList::XamlOptimizedNodeListWriter> m_spWriter;

};

